# tell/plugin.py
#
#

"""

    W E L C O M E  T O  T E L L !!!

    -=-

    (this code is best enjoyed on a wide screen)

"""

## tell imports

from tell import O, j
from .callback import Callback
from .utils import get_name, error

## basic imports

import logging
import imp
import os

## Plugin class

class Plugins(Callback):

    """ contains the plugins (imported modules from datadir/plugs) registered with T E L L. """

    def scan(self, module):
        """ scan the imported plugins on objects with attr set. """
        for name in dir(module):
            if not name: continue
            if "_" in name: continue
            try:
                obj = getattr(module, name)
                otype = getattr(obj, "otype")
                trigger = getattr(obj, "trigger")
            except AttributeError: continue
            if type(trigger) != list: trigger = [trigger, ]
            for t in trigger:
                self.register(otype, t, obj)

    def get_plugnames(self, plugsdir): return [x[:-3] for x in os.listdir(plugsdir) if x.endswith(".py")]

    def load_plugs(self):
        """ load all plugins. """
        path, tail = os.path.split(__file__)
        coreplugsdir = j(path, "plugs")
        todo = [j(self.root, "plugs"), coreplugsdir]
        for plugdir in todo:
            for plugname in self.get_plugnames(plugdir):
                if "__" in plugname: continue
                try: mod = self.load_mod(plugname, plugdir, force=True)
                except: error() ; continue
                if not mod: continue
                self.scan(mod)

    def load_mod(self, plugname, pdir="", force=False):
        """ load a plugin as a module and store it in this object. """
        logging.warn("load.%s" % plugname)
        if plugname in self:
            if not force: return self[plugname]
            self[plugname] = imp.reload(self[plugname])
        else:
            if not pdir: pdir = j(self.root, "plugs")
            search = imp.find_module(plugname, [pdir,])
            mod = imp.load_module(plugname, *search)
            self[plugname] = mod
        return self[plugname]
 
    def unload(self, plugname):
        """ unload a plugin. """
        logging.warn("unload %s" % plugname)
        del self[plugname]

    def reload(self, plugname, force=False):
        """ unload a plugin before loading it. """
        self.unload(plugname)
        mod = self.load_mod(plugname, force)
        self.scan(mod)
        return mod

#### C O M M E N T  -=-  S E C T I O N

""" please write comments on changes you made below, so we can get log of things added/changed. """

## BHJTW 27-11-2012 initial import 
